package com.feiwo.nonego.rpc.serialization.hessian2;

import com.alibaba.com.caucho.hessian.io.Hessian2Input;
import com.alibaba.com.caucho.hessian.io.Hessian2Output;
import com.feiwo.nonego.rpc.serialization.api.Serialization;
import com.feiwo.nonego.rpc.serialization.api.exception.SerializerException;
import com.feiwo.nonego.rpc.spi.annotation.SPIClass;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Objects;

/**
 *
 *
 * @author feiwo 2025-08-13
 */
@SPIClass
public class Hessian2Serialization implements Serialization {

    private static final Logger logger = LoggerFactory.getLogger(Hessian2Serialization.class);

    @Override
    public <T> byte[] serialize(T obj) {
        if (Objects.isNull(obj)) {
            throw new SerializerException("serialization object is null");
        }
        var bytes = new byte[0];
        var byteArrayOutputStream = new ByteArrayOutputStream();
        var hessian2Output = new Hessian2Output(byteArrayOutputStream);

        try {
            hessian2Output.startMessage();
            hessian2Output.writeObject(obj);
            hessian2Output.flush();
            hessian2Output.completeMessage();
            bytes = byteArrayOutputStream.toByteArray();
        } catch (IOException e) {
            throw new SerializerException(e.getMessage(),e);
        }finally {
            try {
                hessian2Output.close();
                byteArrayOutputStream.close();
            } catch (IOException e) {
                logger.error("serialization close stream ex --> ", e);
            }
        }
        return bytes;
    }

    @Override
    public <T> T deserialize(byte[] data, Class<T> clazz) {
        if (Objects.isNull(data)) {
            throw new SerializerException("deserialize data is null");
        }

        var byteInputStream = new ByteArrayInputStream(data);
        var hessian2Input = new Hessian2Input(byteInputStream);
        T object = null;

        try {
            hessian2Input.startMessage();
            //noinspection unchecked
            object = (T) hessian2Input.readObject();
            hessian2Input.completeMessage();
        } catch (IOException e) {
            throw new SerializerException(e.getMessage(), e);
        }finally {
            try {
                hessian2Input.close();
                byteInputStream.close();
            } catch (IOException e) {
                logger.error("deserialize close stream ex --> ", e);
            }
        }
        return object;
    }
}
